<?php
/**
 * @author GhostWei
 * @date Sep 10, 2012
 */
class oauth_open_qzone extends oauth_api_abstract {

	protected $_name = 'qzone';
	protected $scope = array(
			'get_user_info', 'do_like', 'add_share', 'add_topic', 'add_t', 'add_album',
			'list_album', 'list_album', 'upload_pic', 'check_page_fans', 'get_fanslist',
			'notify_tasksys', 'add_idol'
	);
	protected $_url = array(
			'authorize' => 'https://graph.qq.com/oauth2.0/authorize',
			'token' => 'https://graph.qq.com/oauth2.0/token',
			'me' => 'https://graph.qq.com/oauth2.0/me',
			'user_info' => 'https://graph.qq.com/user/get_user_info'
	);
	/**
	 * @return oauth_api_response
	 */
	public function request($action = null, $params = array()) {
		$response = $this->getOauthResponse();
		if(empty($params)) {
			$oauth = $this->getSession()->getToken();
			if(!(isset($oauth['access_token']) && isset($oauth['app_id']) && isset($oauth['app_key']))) {
				return $response->addError('access token is empty or invalid');
			}
			$params = array('access_token' => $oauth['access_token'], 'oauth_consumer_key' => $oauth['app_id'], 'openid' => $oauth['app_key']);
		}
		if($action === null) {
			$url = $this->_url['user_info'];
		} elseif(is_string($action)) {
			$url = $action;
		} else {
			return $response->addError('invalid request');
		}
		$symbol = strpos($url, '?') ? '&' : '?';
		if(!($body = $this->get($url . $symbol . http_build_query($params)))) {
			return $response->addError('HTTP RESPONSE IS NOT OK');
		}
		return $response->setData($body);
	}
	
	/**
	 * @return oauth_open_qzone
	 */
	public function authorize() {
		$request = $this->getRequest();
		$code = $request->getQuery('code');
		$state = $request->getQuery('state');
		if($state && $this->getSession()->getState() != $state) {
			$this->addError('state invalid');
			return $this;
		}
		/**
		 * 获取 access token
		 */
		$p = array();
		$p['grant_type'] = 'authorization_code';
		$p['client_id'] = $this->getSource()->getAppId();
		$p['client_secret'] = $this->getSource()->getAppKey();
		$p['code'] = $code;
		$p['state'] = $state;
		$p['redirect_uri'] = $this->getSession()->getCallback();
		if(!($response = $this->get($this->_url['token'] . '?' . http_build_query($p)))) {
			$this->addError('HTTP RESPONSE IS NOT OK');
			return $this;
		}
		if(1 && $json = $this->parseJson($response)) {
			$this->addError($json->error_description, $json->error);
			return $this;
		}
		parse_str($response, $token);
		if(!(isset($token['access_token']) && isset($token['expires_in']))) {
			$this->addError('access token params error');
			return $this;
		}

		/**
		 * 获取 client_id 和 open_id
		 */
		$p = array('access_token' => $token["access_token"]);
		if(!($response = $this->get($this->_url['me'] . '?' . http_build_query($p)))) {
			$this->addError('HTTP RESPONSE IS NOT OK');
			return $this;
		}
		if(!($json = $this->parseJson($response))) {
			$this->addError($response);
			return $this;
		}
		$this->getSession()->setToken(array(
				'access_token' => $token["access_token"], 
				'app_id' => $json->client_id, 
				'app_key' => $json->openid,
				'expires' => $token["expires_in"]
		));
		return $this;
	}
	
	/**
	 * @param unknown_type $g_ut 仅WAP网站接入时使用。QQ登录页面版本（1：wml版本； 2：xhtml版本），默认值为1
	 */
	public function url($g_ut = null) {
		$p = array();
		$p['response_type'] = 'code';
		$p['client_id'] = $this->getSource()->getAppId();
		$p['redirect_uri'] = $this->getRedirectUrl();
		$p['scope'] = implode(',', $this->scope);
		$p['state'] = $this->getSession()->setState(md5(time()))->getState();
		if($g_ut !== null) {
			$p['display'] = 'mobile';
			if(intval($g_ut) == 1) {
				$p['g_ut'] = 1;
			} else {
				$p['g_ut'] = 2;
			}
		}
		return $this->_url['authorize'] . '?' . http_build_query($p);
	}
	
	private function parseJson($response) {
		if(preg_match('/callback\((.*)\);$/isU', $response, $match)) {
			$json = trim($match[1]);
			try {
				return json_decode($json);
			} catch (Exception $e) {
				$this->addError($e->getMessage());
			}
		}
		return null;
	}
	
}
